/**
 * 基础类型
 */
// import Utils from "./util";
// export * from "./util";
import { BaseMode } from "./interface";
import { Utils } from "./util";
// let myValidator = new ZipCodeValidator();
// myValidator.isAcceptable();

export class BaseTest implements BaseMode{
    run (){
        let util = new Utils();
        //1. boolean
        let isDone:boolean = false;
        util.log(isDone,'boolean');
        //2. number
        let dec:number = 10;
        let hex:number = 0xf00d;
        let binary:number = 0b1010;
        let octal:number = 0o744;
        util.log(hex,'hex');
        util.log(binary,'binary');

        //3. string
        let name:string = "tanson";
        name = "cichy";
        name = `t and c`;
        let age:number = 30;
        let sentence:string = `Hello, my name is ${ name }.

        I'll be ${ age + 1 } years old next month.`;       
        util.log(sentence,'`sentence`');
        //4. array
        let list: number[] = [1, 2, 3];
        let array: Array<number> = [1, 2, 3];
        util.log(list,'list');
        util.log(array,'array');

        //5. 元组 Tuple
        //元组类型允许表示一个已知元素数量和类型的数组，各元素的类型不必相同
        // Declare a tuple type
        let x: [string, number];
        // Initialize it
        x = ['hello', 10]; // OK
        // Initialize it incorrectly
        //x = [10, 'hello']; // Error
        util.log(x[0].substr(1),'Tuple x[0].substr(1)');// OK
        x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型
        util.log(x[3],'Tuple overflow');//当访问一个越界的元素，会使用联合类型替代：

        //TODO: handbook error
        // util.log(x[4].toString(),'Tuple toString');// OK, 'string' 和 'number' 都有 toString
        //x[6] = true; // Error, 布尔不是(string | number)类型

        //6. 枚举enum
        // 默认情况下，从0开始为元素编号，可以手动的指定成员的数值，全部都采用手动赋值    
        // 可以手动的指定成员的数值   
        util.log('=======6.Enum======');     
        enum Color {Red=1, Green, Blue=4};
        let color: Color = Color.Green;
        //枚举类型提供的一个便利是你可以由枚举的值得到它的名字
        let colorName: string = Color[2];
        util.log(color,'enum');
        util.log(colorName, 'enum Color[2]');
        util.log(Color[3],'enum Color[no]');
        // c = "Red";//error
        // util.log(c,'enum=string');
        //const enum cannot get the enum string name;
       // Const enum members are inlined at use sites. const enums cannot have computed members.
       const enum Directions {
            Up,
            Down,
            Left,
            Right
        }
        let a = Directions.Up;
        // let nameOfA = Directions[Directions.Up]; // "A"
        // let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
        // compiler to this: 
        //var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
        util.log(`
        const enum cannot get the enum string name;
        const enum Directions {
            Up,
            Down,
            Left,
            Right
        }
        let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
        compiler to this: 
        var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
        `);

        //7. 任意值 any
        let notSure: any = 4;
        notSure = "maybe a string instead";
        notSure = false; // okay, definitely a boolean
        // notSure.runLog = util.log;      
        // notSure.runLog('any run time function');
        let xxArray: any[] = [1, true, "free"];
        xxArray[1] = "100"; //修改Boolean为number
        util.log(xxArray,'xxArray');
        //8. 空值 void 
        //void类型像是与any类型相反，它表示没有任何类型
        //因为你只能为它赋予undefined和null
        function warnUser(): void {
            alert("This is my warning message");
        }

        //9. Null 和 Undefined
        // TypeScript里，undefined和null两者各自有自己的类型分别叫做undefined和null
        // Not much else we can assign to these variables!
        // 当你指定了--strictNullChecks标记，null和undefined只能赋值给void和它们各自。
        // 这能避免 很多常见的问题。 也许在某处你想传入一个 string或null或undefined，你可以使用联合类型string | null | undefined。
        // 注意：我们鼓励尽可能地使用--strictNullChecks，但在本手册里我们假设这个标记是关闭的。
        let u: undefined = undefined;
        let n: null = null;

        //10. Never
        //never类型表示的是那些永不存在的值的类型
        // 返回never的函数必须存在无法达到的终点
        function error(message: string): never {
            throw new Error(message);
        }

        // 推断的返回值类型为never
        function fail() {
            return error("Something failed");
        }

        // 返回never的函数必须存在无法达到的终点
        function infiniteLoop(): never {
            while (true) {
            }
        }
        
        
        //类型断言
        //类型断言好比其它语言里的类型转换，但是不进行特殊的数据检查和解构。
        //它没有运行时的影响，只是在编译阶段起作用。
        let someValue: any = "this is a string";
        // let someValue: any = 12345678; //(someValue as string).length undefined
        // let someValue: any = [1,23,456,78]; //(someValue as string).length 4
        let strLength: number = (someValue as string).length;
        util.log(someValue,"any string");
        util.log(strLength,"any as string");
        // util.log(([1,23,456,78] as number),"array as number"); //编译阶段报错,运行没影响,输出：[ 1, 23, 456, 78 ]
        // util.log(("123456" as number)+1,"string as number+1"); //编译阶段报错,运行没影响,输出：1234561
        // util.log(([1,23,456,78] as number)+1,"array as number+1");//编译阶段报错,运行没影响,输出：1,23,456,781
        
     
    };
}


